home *** CD-ROM | disk | FTP | other *** search
/ X User Tools / X User Tools (O'Reilly and Associates)(1994).ISO / sources / xcol / part01.z / part01
Internet Message Format  |  1994-09-27  |  34KB

  1. Path: j.cc.purdue.edu!mentor.cc.purdue.edu!purdue!mailrus!uunet!cs.utexas.edu!samsung!brutus.cs.uiuc.edu!apple!sun-barr!newstop!sun!informatik.uni-kl.de
  2. From: hoenig@informatik.uni-kl.de (Helmut Hoenig)
  3. Newsgroups: comp.sources.x
  4. Subject: v06i047: Xcol -- Color-Selector, Part01/02
  5. Message-ID: <133326@sun.Eng.Sun.COM>
  6. Date: 22 Mar 90 18:57:36 GMT
  7. Sender: news@sun.Eng.Sun.COM
  8. Lines: 1159
  9. Approved: argv@sun.com
  10.  
  11. Submitted-by: Helmut Hoenig <hoenig@informatik.uni-kl.de>
  12. Posting-number: Volume 6, Issue 47
  13. Archive-name: xcol/part01
  14.  
  15. XCol is a program to edit occurrences of color-names in text-files
  16. (i.e. the '.twmrc'-file). It shows the available colors and you can
  17. change the textfile by selecting new colors with the mouse.
  18.  
  19. Even without editing a textfile, it gives you a good impression
  20. of the available colors (the colors defined in the 'rgb.txt'-file
  21. of the server).
  22.  
  23. The program runs on X11R4. It should run on X11R3 too, but I
  24. already had some small problems with the created colormap.
  25. A manual page is included.
  26.  
  27. by Helmut Hoenig
  28. hoenig@informatik.uni-kl.de
  29.  
  30. -------------------------------------------------------------------
  31. #! /bin/sh
  32. # This is a shell archive.  Remove anything before this line, then unpack
  33. # it by saving it into a file and typing "sh file".  To overwrite existing
  34. # files, type "sh file -c".  You can also feed this as standard input via
  35. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  36. # will see the following message at the end:
  37. #        "End of shell archive."
  38. # Contents:  xcol.txt makefile Imakefile patchlevel.h xcol.part1
  39. # Wrapped by hoenig@popper on Wed Mar 21 16:47:26 1990
  40. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  41. if test -f xcol.txt -a "${1}" != "-c" ; then 
  42.   echo shar: Will not over-write existing file \"xcol.txt\"
  43. else
  44. echo shar: Extracting \"xcol.txt\" \(3824 characters\)
  45. sed "s/^X//" >xcol.txt <<'END_OF_xcol.txt'
  46. XNAME
  47. X     xcol - change color-entries in textfiles
  48. X
  49. XSYNOPSIS
  50. X     xcol [-options ...] [filename]
  51. X
  52. XDESCRIPTION
  53. X     XCol displays the colors defined in the rgb.txt-file of  the
  54. X     XServer.   The  colors  are  sorted by their names and their
  55. X     RGB-values and shown in a cube in the ColorView-Window  (The
  56. X     positions  represent  the  RGB-values).  Since there usually
  57. X     are more colors defined in the file than cells in the color-
  58. X     map, entries with the same name but different RGB-values for
  59. X     different intensities, are grouped together.
  60. X
  61. X     If a filename is given as a parameter,  all  occurrences  of
  62. X     color-names   in  that  file  are  shown  in  an  additional
  63. X     TextView-Window. To change the colors, a text-line has to be
  64. X     made  active.  Afterwards a new color can be selected in the
  65. X     ColorView-Window. To get a better impression of the color, a
  66. X     help-color  (background) can be selected for each text-line.
  67. X     If 2 lines define a foreground and a  background  color,  an
  68. X     association  can be made and the colors of both lines can be
  69. X     selected together.
  70. X
  71. XBUTTONS
  72. X     in ColorView-Window
  73. X
  74. X          left:   select color for the active line.
  75. X          middle: select help-color for the active line.
  76. X          right:  warp pointer to color of active line.
  77. X
  78. X     in TextView-Window
  79. X
  80. X          left:   select line as active line.
  81. X          middle: toggle reverse-mode or
  82. X                  connect/disconnect 2 lines.
  83. X          right:  show line in the textfile.
  84. X
  85. XOPTIONS
  86. X     -rv     Color-positions are reversed in the cube.  Some  new
  87. X             colors  can  become  visible in the area of the very
  88. X             bright colors.
  89. X
  90. X     -b<n>   The size of color blocks is set to the constant <n>.
  91. X             By   default,   it   depends  on  the  size  of  the
  92. X             ColorView-Window.
  93. X
  94. X     -gran<n>
  95. X             The maximum number of associated colors  is  set  to
  96. X             <n>.  By default, this value is 11. (You can see the
  97. X             effect  when  reaching  the  grey-field,  where  101
  98. X             associated entries are possibly available.)
  99. X
  100. X     -dark<n>
  101. X             The percentage of the intensity of other colors  can
  102. X             be  set  (default:  50).  It  is  easier to select a
  103. X             color, if the screen is darkened a little bit.
  104. X
  105. X     +<char_list>
  106. X             add characters to list of 'space'-chars. The  color-
  107. X             string  in  the  textfile  has  to  occur  between 2
  108. X             'space'-chars to be recognized.  By  default,  these
  109. X             letters are ' ', '\t', '\n', ':', '"'.
  110. X
  111. X     -strings
  112. X             Names of colors in the file are only recognized when
  113. X             used  in a string (useful for C-Sources). This means
  114. X             that the list of 'space'-chars is set to '"' only.
  115. X
  116. X     -case   All occurrences of color-names  in  wrong  case  are
  117. X             replaced by the color-name of the 'rgb.txt'-file.
  118. X
  119. X     -help   print some instructions (usage of buttons).
  120. X
  121. X     -file <name>
  122. X             name of a different 'rgb.txt'-file.
  123. X
  124. XFILES
  125. X     /usr/lib/X11/rgb.txt
  126. X
  127. XSEE ALSO
  128. X     X(1)
  129. X
  130. XBUGS
  131. X     Actually I wanted the program to  work  with  the  selection
  132. X     mechanism  used in xterm (when no textfile is given), but it
  133. X     seems to be too complicated to use it here.  So, the current
  134. X     version   always   stores   the   string  of  the  color  in
  135. X     CUT_BUFFER0.  If anyone has an easy way to use  the  correct
  136. X     selection mechanism, please inform me.
  137. X
  138. XCOPYRIGHT
  139. X     Copyright 1990, University of Kaiserslautern.
  140. X
  141. X     Author: Helmut Hoenig (hoenig@informatik.uni-kl.de)
  142. X
  143. X     Permission  to  use,  copy,  modify,  and  distribute   this
  144. X     software  for any purpose and without fee is hereby granted,
  145. X     provided that the  above  copyright  notice  appear  in  all
  146. X     copies.
  147. END_OF_xcol.txt
  148. if test 3824 -ne `wc -c <xcol.txt`; then
  149.     echo shar: \"xcol.txt\" unpacked with wrong size!
  150. fi
  151. # end of overwriting check
  152. fi
  153. if test -f makefile -a "${1}" != "-c" ; then 
  154.   echo shar: Will not over-write existing file \"makefile\"
  155. else
  156. echo shar: Extracting \"makefile\" \(99 characters\)
  157. sed "s/^X//" >makefile <<'END_OF_makefile'
  158. XCFLAGS = 
  159. XLIBS   = -lX11
  160. XG_OBJ  = xcol.o
  161. X
  162. Xxcol:    $(G_OBJ)
  163. X    $(CC) $(CFLAGS) $(G_OBJ) $(LIBS) -o xcol
  164. END_OF_makefile
  165. if test 99 -ne `wc -c <makefile`; then
  166.     echo shar: \"makefile\" unpacked with wrong size!
  167. fi
  168. # end of overwriting check
  169. fi
  170. if test -f Imakefile -a "${1}" != "-c" ; then 
  171.   echo shar: Will not over-write existing file \"Imakefile\"
  172. else
  173. echo shar: Extracting \"Imakefile\" \(78 characters\)
  174. sed "s/^X//" >Imakefile <<'END_OF_Imakefile'
  175. X           SRCS = xcol.c
  176. X           OBJS = xcol.o
  177. X
  178. XComplexProgramTarget(xcol)
  179. END_OF_Imakefile
  180. if test 78 -ne `wc -c <Imakefile`; then
  181.     echo shar: \"Imakefile\" unpacked with wrong size!
  182. fi
  183. # end of overwriting check
  184. fi
  185. if test -f patchlevel.h -a "${1}" != "-c" ; then 
  186.   echo shar: Will not over-write existing file \"patchlevel.h\"
  187. else
  188. echo shar: Extracting \"patchlevel.h\" \(53 characters\)
  189. sed "s/^X//" >patchlevel.h <<'END_OF_patchlevel.h'
  190. X#define    PATCHLEVEL    0
  191. X#define    PATCHDATE    "Mar-21-1990"
  192. END_OF_patchlevel.h
  193. if test 53 -ne `wc -c <patchlevel.h`; then
  194.     echo shar: \"patchlevel.h\" unpacked with wrong size!
  195. fi
  196. # end of overwriting check
  197. fi
  198. if test -f xcol.part1 -a "${1}" != "-c" ; then 
  199.   echo shar: Will not over-write existing file \"xcol.part1\"
  200. else
  201. echo shar: Extracting \"xcol.part1\" \(24317 characters\)
  202. sed "s/^X//" >xcol.part1 <<'END_OF_xcol.part1'
  203. X/****************************************************************
  204. X *                                *
  205. X *  xcol - program to edit color-name-occurrences in textfiles    *
  206. X *                                *
  207. X *         Written by Helmut Hoenig, Feb. 1990.        *
  208. X *        University of Kaiserslautern, Germany        *
  209. X *                                *
  210. X *         email: hoenig@informatik.uni-kl.de            *
  211. X *                                *
  212. X ****************************************************************/
  213. X
  214. X#include <X11/Xlib.h>
  215. X#include <X11/Xutil.h>
  216. X#include <X11/cursorfont.h>
  217. X
  218. X#include <sys/param.h>
  219. X#include <stdio.h>
  220. X#include <strings.h>
  221. X#include <ctype.h>
  222. X
  223. X#include "patchlevel.h"
  224. X
  225. X/*----------------------------------------------------------------------------*/
  226. X
  227. X#define    COLOR_FONT    "-adobe-times-bold-r-normal--17-120-100-100-p-88-iso8859-1"
  228. X#define    TEXT_FONT    "-adobe-times-bold-r-normal--12-120-75-75-p-67-iso8859-1"
  229. X
  230. X#define    RGB_FILE    "/usr/lib/X11/rgb.txt"
  231. X
  232. X/* MAX_??? - definitions are used in the definition of some local arrays, 
  233. X   where I didn't want to make complicated memory allocation.        */
  234. X
  235. X#define    MAX_CELLS    256    /* number of cells, used by the programm*/
  236. X
  237. X#define    MAX_COLS    1000    /* colors in rgb.txt-file        */
  238. X#define    MAX_COLOR_LINES    400    /* color occurrences in a textfile    */
  239. X#define    MAX_LINE_LENGTH    1000    /* linelength of textfile        */
  240. X
  241. X/*----------------------------------------------------------------------------*/
  242. X
  243. X/* switch on/off some bugs ?? */
  244. X#define    CHG_TEXT_WINDOW_COLORMAP
  245. X#define _RECOLOR_CURSOR
  246. X
  247. X/* variables for parameters (default is set) */
  248. Xint        reverse    = 0;
  249. Xint        BO_def    = 0;
  250. Xint        darkness=50;
  251. Xint        gran    =11;
  252. Xint        original= 0;
  253. X
  254. X/* X-Data */
  255. XDisplay        *display;
  256. XScreen        *screen;
  257. XXFontStruct    *finfo;
  258. XGC        gc;
  259. Xint        cells;
  260. X
  261. X/* the grey-pixmap is used to get an impression of mixing the foreground
  262. X * and background color of a color-line.
  263. X */
  264. X#define grey_width 16
  265. X#define grey_height 16
  266. Xstatic char grey_bits[] = {
  267. X   0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 
  268. X   0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 
  269. X   0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa, 
  270. X   0x55, 0x55, 0xaa, 0xaa, 0x55, 0x55, 0xaa, 0xaa};
  271. XPixmap    grey_pixmap;
  272. X
  273. XCursor    mw_cursor;    /* Cursor in main-window            */
  274. XCursor    tw_cursor;    /* Cursor in text-window            */
  275. XCursor    subsel_cursor;    /* Cursor during selection of associated colors */
  276. XCursor    text_cursor;    /* Cursor while looking in the source-file    */
  277. XCursor    quest_cursor;    /* Cursor while asking for write-confirmation    */
  278. XCursor    updown_cursor;    /* Cursor while making association        */
  279. X
  280. X/* Mainwindow-Data */
  281. XWindow        mw;    /* Window-Id */
  282. Xint        dx, dy;    /* current size of the window */
  283. Xint        BO=14;    /* current size of the color-boxes in the window */
  284. X
  285. X/* Textwindow-Data */
  286. XWindow        tw = NULL;
  287. XXFontStruct    *tinfo;            /* Structure of the textfont */
  288. Xint        char_width, char_height;/* char-size depending on the font */
  289. Xchar        *tw_message[2];        /* messages in header and footer-line */
  290. Xint        twidth;            /* width in pixel */
  291. Xint        tw_lines;        /* height in lines (header&footer not included) */
  292. Xint        act_line=0;        /* active-line */
  293. Xint        act_offset=0;        /* first color-line (when not all lines fit in the window) */
  294. X
  295. X/* Subwindow-Data (little window for selected color) */
  296. XWindow        subw;        /* Window-Id */
  297. Xint        sdx, sdy;    /* current size of subwindow */
  298. Xint        subcols;    /* number of associated colors in the subwindow */
  299. X
  300. X/* Color-Management */
  301. XColormap    my_map=NULL;
  302. Xint        my_pixel[MAX_CELLS];    /* flag: 0 = pixel not used in my program */
  303. Xint        only_mine;    /* flag: 1 = allocations only in own map */
  304. X
  305. X#define    NotAllocated    (-1L)
  306. X#define    Undefined    (-2L)
  307. X
  308. Xtypedef    struct _color_def {
  309. X    int            r, g, b;    /* rgb-value from the 'rbg.txt'-file */
  310. X    char            *name;    /* name from the 'rgb.txt'-file */
  311. X    int            x, y;    /* position in main window    */
  312. X    unsigned long        pixel;    /* allocated pixel for the color */
  313. X    struct    _color_def    *associated;    /* colors with different intensity (e.g. 'blue' -> 'blue4' ... ) */
  314. X    struct    _color_def    *brother;    /* colors with different name (e.g. 'OldLace' -> 'old lace') */
  315. X} ColorDef;
  316. X
  317. Xtypedef    struct _color_strings {
  318. X    char        *name;
  319. X    int        length;
  320. X    ColorDef    *def;
  321. X} ColorString;
  322. X
  323. XColorDef    *color[MAX_COLS];    /* field with the definitions of the colors */
  324. XColorString    cname[MAX_COLS];    /* sorted field with the names of all colors */
  325. XColorString    *first[256];        /* 'Hash-Table', points to the first name
  326. X                       that starts with the given letter. */
  327. X
  328. Xint    color_names;    /* number of color-names
  329. X               = entries in the 'rgb.txt'-file */
  330. Xint    color_number;    /* number of 'different' colors
  331. X               = number of colors shown in the cube */
  332. X
  333. X#define    BLACK_STRING    "black"
  334. X#define    WHITE_STRING    "white"
  335. X#define    GREY_STRING    "gray"
  336. X
  337. XColorDef std_black = {   0,   0,   0, BLACK_STRING };
  338. XColorDef std_white = { 255, 255, 255, WHITE_STRING };
  339. XColorDef std_grey  = { 192, 192, 192, GREY_STRING  };
  340. X
  341. Xunsigned long    white, black, grey;    /* pixel-values (in my_map !!) */
  342. XColorDef *back_def;            /* default background in textwindow */
  343. X
  344. X/*----------------------------------------------------------------------------*/
  345. X
  346. Xtypedef    struct    _text_line {    /* structure to store the text-file */
  347. X    char            *contents;
  348. X    struct    _text_line    *next;
  349. X    struct    _text_line    *previous;
  350. X} TextLine;
  351. X
  352. Xtypedef    struct    _color_line {    /* structure for a line with color-entry */
  353. X    TextLine    *line;        /* pointer to the textline */    
  354. X    ColorDef    *color;        /* the color defined in the line */
  355. X    ColorDef    *help;        /* a help-color for the background */
  356. X    int        reverse;    /* flag to display line in reverse */
  357. X    int        pos_in_line;    /* position of the color-name in the line */
  358. X    int        assoc;        /* corresponding color-line, when a
  359. X                       'foreground-background'-association
  360. X                       was found (or entered) */
  361. X} ColorLine;
  362. X
  363. Xchar        *file_name;        /* name of the text-file */
  364. XTextLine    *loaded_text;        /* Pointer to the first line */
  365. XColorLine    line[MAX_COLOR_LINES];    /* array of the color-lines */
  366. Xint        color_lines;        /* number of the color-lines */
  367. Xint        longest_colored;    /* length of the longest color-line */
  368. X
  369. Xchar    space_char[256];        /* flag, which chars should be recognized
  370. X                       as spaces */
  371. X
  372. X
  373. X/********************************************************************************
  374. X *        parsing the text-file (not very efficient, but who cares)        *
  375. X ********************************************************************************/
  376. X
  377. X
  378. Xvoid set_default_spaces()
  379. X{
  380. X    memset( space_char, 0, (int)sizeof(space_char) );
  381. X    space_char[ ' ' ] = space_char[ '\t' ] = space_char[ '\n' ] = 
  382. X    space_char[ ':' ] = space_char[ '"' ] = 1;
  383. X}
  384. X
  385. Xint strncase_equal( s1, s2, n )
  386. X    register char    *s1;
  387. X    register char    *s2;
  388. X    register int    n;
  389. X/* the function is NOT correct, since just proves, if strings are equal
  390. X   when the 5th bit of their characters is ignored.
  391. X */
  392. X{
  393. X    while(n--)
  394. X    {    if ( ((*s1++)^(*s2++))&((unsigned char)~32) )    return(1);
  395. X    }
  396. X    return(0);
  397. X}
  398. X
  399. Xint strcase_equal( s1, s2 )
  400. X    char    *s1,*s2;
  401. X{
  402. Xint    n1,n2;
  403. X
  404. X    n1 = strlen(s1);
  405. X    n2 = strlen(s2);
  406. X    if (n1!=n2)    return(-1);
  407. X    else        return(strncase_equal( s1, s2, n1 ));
  408. X}
  409. X
  410. Xstring_exchange( cline, new_color )
  411. X    ColorLine    *cline;
  412. X    ColorDef    *new_color;
  413. X/* replaces the color-string in a color-line */
  414. X{
  415. Xchar    new_line[MAX_LINE_LENGTH];
  416. Xint    pos;
  417. X
  418. X    pos = cline->pos_in_line;
  419. X    strncpy( &new_line[0], cline->line->contents, pos );
  420. X    strcpy( &new_line[pos], new_color->name );
  421. X    strcat( new_line, &cline->line->contents[pos+strlen(cline->color->name)] );
  422. X    free( cline->line->contents );
  423. X    cline->line->contents = (char *)malloc((unsigned) strlen( new_line )+1 );
  424. X    strcpy( cline->line->contents, new_line );
  425. X}
  426. X
  427. Xvoid check_colors( in_line )
  428. X    TextLine    *in_line;
  429. X/* checks, if a color exists in the given line and possibly adds
  430. X * the line to the list of color-lines.
  431. X */
  432. X{
  433. Xint        i, c;
  434. Xchar        lett;
  435. Xchar        check;
  436. XColorString    *col;
  437. Xchar        *act_line = in_line->contents;
  438. X
  439. X    c=strlen(act_line);
  440. X    while(c>0)
  441. X    {   do
  442. X        {    c--;
  443. X        if (space_char[act_line[c-1]])    break;
  444. X        }
  445. X        while(c>1);
  446. X
  447. X        lett = act_line[c];
  448. X        if (isalpha(lett))
  449. X        {
  450. X            if (isupper(lett))    lett = tolower( lett );
  451. X    /* compares both cases */
  452. X        for (i=0;i<2;i++)
  453. X        {    for (col=first[lett];col<first[lett+1];col++)
  454. X            {
  455. X                check = act_line[c+col->length];
  456. X            if (space_char[check])
  457. X            {    if ((strncase_equal( &act_line[c], col->name, col->length )==0 ))
  458. X                {    line[color_lines].line = in_line;
  459. X                    line[color_lines].color= col->def;
  460. X                    line[color_lines].help = back_def;
  461. X                    line[color_lines].pos_in_line = c;
  462. X                    line[color_lines].reverse = 0;
  463. X                    line[color_lines].assoc = -1;
  464. X
  465. X                    if (original)
  466. X                    {    string_exchange( &line[color_lines], col->def );
  467. X                    }
  468. X                    if (XTextWidth( tinfo, act_line, strlen(act_line) )>longest_colored)
  469. X                        longest_colored = XTextWidth( tinfo, act_line, strlen(act_line) );
  470. X                    color_lines++;
  471. X                    return;
  472. X                }
  473. X            }
  474. X            }
  475. X            lett = toupper( lett );
  476. X        }
  477. X        }
  478. X    }
  479. X}
  480. X
  481. Xint spc_line( search_string, line, name, length )
  482. X    char        *search_string;
  483. X    TextLine    *line;
  484. X    char        *name;
  485. X    int        *length;
  486. X/* searches for the search-string in the given line. If it exists, the name
  487. X * in front of the search-string is copied to name and its length is returned.
  488. X */
  489. X{
  490. Xint    c, sl, cs;
  491. X
  492. X    c = strlen( line->contents );
  493. X    sl = strlen(search_string);
  494. X    while( c>0 )
  495. X    {    if (strncase_equal( search_string, &line->contents[c], sl )==0)
  496. X        {    cs=c;
  497. X            do
  498. X            {    cs--;
  499. X                if (isspace(line->contents[cs]))    break;
  500. X            }
  501. X            while(cs>0);
  502. X            *length = c-cs;
  503. X            if (cs)
  504. X            {    (*length)--;    cs++;
  505. X            }
  506. X
  507. X            strncpy( name, &line->contents[cs], *length );
  508. X            name[*length]='\0';
  509. X            return(1);
  510. X        }
  511. X        c--;
  512. X    }
  513. X    return(0);
  514. X}
  515. X
  516. Xvoid find_assocs()
  517. X/* tries to find 'Foreground-Background'-Associations in the Color-Lines */
  518. X{
  519. Xint    i, j;
  520. Xchar    name1[100], name2[100];
  521. Xint    length1, length2;
  522. X
  523. X    for (i=0;i<color_lines;i++)
  524. X    {    if (spc_line("foreground", line[i].line, name1, &length1))
  525. X        {    for (j=i+1;j>=i-1;j-=2)
  526. X            {   if ((j>=0)&&(j<color_lines))
  527. X                {    if (spc_line("background", line[j].line, name2, &length2))
  528. X                {
  529. X                    if (strcmp(name1, name2)==0)
  530. X                    {    line[i].reverse=0;
  531. X                        line[i].help = line[j].color;
  532. X                        line[i].assoc= j;
  533. X
  534. X                        line[j].reverse=1;
  535. X                        line[j].help = line[i].color;
  536. X                        line[j].assoc= i;
  537. X                    }
  538. X                }
  539. X                }
  540. X            }
  541. X        }
  542. X        else if ((spc_line("background", line[i].line, name1, &length1))&&(line[i].assoc<0))
  543. X        {    for (j=i+1;j>=i-1;j-=2)
  544. X            {   if ((j>=0)&&(j<color_lines))
  545. X                {    if (spc_line("border", line[j].line, name2, &length2))
  546. X                {
  547. X                    if (strcmp(name1, name2)==0)
  548. X                    {    line[i].reverse=1;
  549. X                        line[i].help = line[j].color;
  550. X                        line[i].assoc= j;
  551. X
  552. X                        line[j].reverse=0;
  553. X                        line[j].help = line[i].color;
  554. X                        line[j].assoc= i;
  555. X                    }
  556. X                }
  557. X                }
  558. X            }
  559. X        }
  560. X    }
  561. X}
  562. X
  563. Xint load_file( fname )
  564. X    char    *fname;
  565. X/* loads the text-file and tries to find color-entries in each line */
  566. X{
  567. XFILE        *fp;
  568. XTextLine    *act, *next;
  569. Xchar        linebuffer[MAX_LINE_LENGTH];
  570. X
  571. X/* load the file with colors */
  572. X    longest_colored = 0;
  573. X    color_lines = 0;
  574. X
  575. X    fp = fopen( fname, "r" );
  576. X    if (fp==NULL)
  577. X    {    fprintf( stderr, "can't load file '%s'.\n", fname );
  578. X        return(0);
  579. X    }
  580. X
  581. X    loaded_text = act = NULL;
  582. X    while (fgets( linebuffer, sizeof linebuffer, fp )!=NULL)
  583. X    {    next = (TextLine *)malloc((unsigned)sizeof(TextLine));
  584. X        next->contents = (char *)malloc((unsigned)strlen(linebuffer)+1);
  585. X        strcpy( next->contents, linebuffer );
  586. X
  587. X        check_colors( next );
  588. X        if (act==NULL)
  589. X        {    loaded_text=act    = next;
  590. X            next->previous    = NULL;
  591. X        }
  592. X        else
  593. X        {    act->next    = next;
  594. X            next->previous    = act;
  595. X            act = next;
  596. X        }
  597. X    }
  598. X    fclose( fp );
  599. X    act->next=NULL;
  600. X    return(1);
  601. X}
  602. X
  603. Xint write_file( fname )
  604. X    char    *fname;
  605. X{
  606. XFILE        *fp;
  607. XTextLine    *act;
  608. X
  609. X    fp = fopen( fname, "w" );
  610. X    if (fp==NULL)    return(-1);
  611. X    act = loaded_text;
  612. X    while( act )
  613. X    {    if (fputs( act->contents, fp )==EOF)
  614. X        {    fprintf(stderr, "write error on file '%s'\n", fname);
  615. X            fclose(fp);
  616. X            return(-2);
  617. X        }
  618. X        act = act->next;
  619. X    }
  620. X    fclose( fp );
  621. X    return(0);
  622. X}
  623. X
  624. X
  625. X/********************************************************************************
  626. X *        allocating, freeing, sorting, searching COLORS.            *
  627. X ********************************************************************************/
  628. X
  629. X
  630. XColorDef *find_color( name )
  631. X    char    *name;
  632. X/* searches in the tree of colordefinitions for the named color */
  633. X{
  634. XColorDef    *erg, *assoc;
  635. Xint        i;
  636. X
  637. X    for (i=0;i<color_number;i++)
  638. X    {    erg = color[i];
  639. X        do
  640. X        {
  641. X            if (strcase_equal(erg->name, name)==0)    return( erg );
  642. X            assoc = erg->associated;
  643. X            while( assoc )
  644. X            {    if (strcase_equal(assoc->name, name)==0)    return( assoc );
  645. X                assoc = assoc->associated;
  646. X            }
  647. X            erg = erg->brother;
  648. X        }
  649. X        while (erg);
  650. X    }
  651. X    return(NULL);
  652. X}
  653. X
  654. Xvoid load_color( act )
  655. X    ColorDef *act;
  656. X/* allocates a pixel for the color, if it is not already allocated. When it's
  657. X * still possible to allocate pixels in the DefaultColormap, this is done and
  658. X * the same color is stored in both maps. If no more cells are available in
  659. X * the DefaultColormap, the program continues working only in its own map.
  660. X */
  661. X{
  662. XXColor    scr;
  663. Xlong    pixel;
  664. X
  665. X    if (act->pixel==NotAllocated)
  666. X    {    if (!only_mine)
  667. X        {    if ( (!XAllocColorCells( display, DefaultColormapOfScreen(screen), True, 
  668. X                NULL, 0, (unsigned long*)&pixel, 1 )) || (pixel>=cells) )
  669. X            {
  670. X                for (pixel=0;pixel<cells;pixel++)
  671. X                {
  672. X                    if (my_pixel[pixel])
  673. X                    {    XFreeColors( display, DefaultColormapOfScreen(screen), 
  674. X                            (unsigned long*)&pixel, 1, 0 );
  675. X                    }
  676. X                }
  677. X
  678. X                only_mine=1;
  679. X#ifdef CHG_TEXT_WINDOW_COLORMAP
  680. X/* when switched on, all windows (not only the textwindow), are displayed
  681. X * in my Colormap, when the DefaultColormap hasn't got any more cells available.
  682. X * Try the option -gran100 and search for the 'gray'-color in the main-window
  683. X * to reach the extremes of the program.
  684. X */
  685. X                if (tw)
  686. X                {    XSetWindowColormap( display, tw, my_map );
  687. X                }
  688. X#endif
  689. X            }
  690. X        }
  691. X        if (only_mine)
  692. X        {    for (pixel=cells-1;pixel>=0;pixel--)
  693. X            {    if (my_pixel[pixel]==0)    break;
  694. X            }
  695. X    /* the reaction to an overflow in the color-map is hard, but
  696. X     * I can't think of an easy solution for that problem.
  697. X     */        if (pixel<0)
  698. X            {    fprintf( stderr, "You did it. The Colormap if full.\n");
  699. X                if (CellsOfScreen(screen)>MAX_CELLS)
  700. X                {    fprintf( stderr, "Compile the program again with the\n");
  701. X                    fprintf( stderr, "MAX_CELLS-macro set to an higher value.\n");
  702. X                }
  703. X                exit(0);
  704. X            }
  705. X        }
  706. X        act -> pixel = pixel;
  707. X        scr.pixel = pixel;
  708. X        scr.flags = DoRed | DoGreen | DoBlue;
  709. X        scr.red   = act->r << 8;
  710. X        scr.green = act->g << 8;
  711. X        scr.blue  = act->b << 8;
  712. X        XStoreColor( display, my_map, &scr );
  713. X        if (!only_mine)
  714. X            XStoreColor( display, DefaultColormapOfScreen(screen), &scr );
  715. X    }
  716. X    my_pixel[act->pixel]++;
  717. X}
  718. X
  719. Xvoid unload_color( act )
  720. X    ColorDef *act;
  721. X/* The color is not used anymore. It is possible that the color was loaded
  722. X * more than once and therefor, the cell can't be freed.
  723. X */
  724. X{
  725. X    if (act->pixel==NotAllocated)    return;
  726. X
  727. X    if ((--my_pixel[act->pixel])==0)
  728. X    {    if (!only_mine)
  729. X        {    XFreeColors( display, DefaultColormapOfScreen(screen), 
  730. X                    &act->pixel, 1, 0 );
  731. X        }
  732. X        act->pixel=NotAllocated;
  733. X    }
  734. X}
  735. X
  736. Xvoid load_text_colors()
  737. X/* to load all colors used in the color-lines of the text-file */
  738. X{
  739. Xint i;
  740. X
  741. X    for (i=0;i<color_lines;i++)
  742. X    {    load_color( line[i].color );
  743. X        load_color( line[i].help  );
  744. X    }
  745. X}
  746. X
  747. Xvoid exchange( old, new )
  748. X    ColorDef    **old;
  749. X    ColorDef    *new;
  750. X/* correct exchanging of a loaded color */
  751. X{
  752. X    if (*old)
  753. X    {    unload_color( *old );
  754. X    }
  755. X    load_color( new );
  756. X    *old = new;
  757. X}
  758. X
  759. X/*----------------------------------------------------------------------------*/
  760. X
  761. X/*
  762. X * functions to sort the colors
  763. X */
  764. X
  765. Xint color_name_sort( p1, p2 )
  766. X    ColorString    *p1, *p2;
  767. X{
  768. X    return(strcmp(p1->name, p2->name));
  769. X}
  770. X
  771. Xint color_sort( p1, p2 )
  772. X    ColorDef    **p1, **p2;
  773. X{
  774. Xchar    *s1, *s2;
  775. X
  776. X    if ((*p1)->b!=(*p2)->b)    return(((*p1)->b>(*p2)->b)?1:-1);
  777. X    if ((*p1)->g!=(*p2)->g)    return(((*p1)->g>(*p2)->g)?1:-1);
  778. X    if ((*p1)->r!=(*p2)->r)    return(((*p1)->r>(*p2)->r)?1:-1);
  779. X    s1 = index((*p1)->name, ' ');
  780. X    s2 = index((*p2)->name, ' ');
  781. X    s1 = s2 = NULL;
  782. X
  783. X    if (s1)
  784. X    {    if (s2)    return(strcmp((*p1)->name, (*p2)->name));
  785. X        else    return(1);
  786. X    }
  787. X    else
  788. X    {    if (s2)    return(-1);
  789. X        else    return(strcmp((*p1)->name, (*p2)->name));
  790. X    }
  791. X}
  792. X
  793. Xint color_sort_r( p1, p2 )
  794. X    ColorDef    **p1, **p2;
  795. X{
  796. X    if ((*p1)->b!=(*p2)->b)    return(((*p1)->b>(*p2)->b)?-1:1);
  797. X    if ((*p1)->g!=(*p2)->g)    return(((*p1)->g>(*p2)->g)?-1:1);
  798. X    if ((*p1)->r!=(*p2)->r)    return(((*p1)->r>(*p2)->r)?-1:1);
  799. X    return(0);
  800. X}
  801. X
  802. Xvoid brother_sort( first )
  803. X    ColorDef    **first;
  804. X{
  805. XColorDef *list[1000];
  806. Xint     length;
  807. X
  808. X    length = 0;
  809. X
  810. X    list[length] = *first;
  811. X    while(list[length]->brother)
  812. X    {    list[length+1] = list[length]->brother;
  813. X        length++;
  814. X    }
  815. X
  816. X    qsort( (char *)list, length+1, sizeof(ColorDef *), color_sort );
  817. X
  818. X    list[length]->brother = NULL;
  819. X
  820. X    while(length>0)
  821. X    {    list[length-1]->brother = list[length];
  822. X        length--;
  823. X    }
  824. X    *first = list[0];
  825. X}
  826. X
  827. Xvoid associated_sort( first )
  828. X    ColorDef    *first;
  829. X{
  830. XColorDef *list[1000];
  831. Xint     length;
  832. X
  833. X    length = 0;
  834. X
  835. X    list[length] = first;
  836. X    while(list[length]->associated)
  837. X    {    list[length+1] = list[length]->associated;
  838. X        length++;
  839. X    }
  840. X
  841. X    qsort( (char *)&list[1], length, sizeof(ColorDef *), color_sort );
  842. X
  843. X    list[length]->associated = NULL;
  844. X
  845. X    while(length>0)
  846. X    {    list[length-1]->associated = list[length];
  847. X        length--;
  848. X    }
  849. X}
  850. X
  851. X/*----------------------------------------------------------------------------*/
  852. X
  853. X/*
  854. X * functions to load the color-file and build the tree with colordefinitions
  855. X */
  856. X
  857. Xchar *cut_digits( name )
  858. X    char    *name;
  859. X/* cuts digits from a color-string. returns a pointer to a static string
  860. X * which of course must not be freed. if there where no digits, the original
  861. X * pointer is returned.
  862. X */
  863. X{
  864. Xstatic char short_name[40];
  865. Xint i;
  866. X
  867. X    i = strlen(name);
  868. X    if ((i>39)||(!isdigit(name[i-1])))    return(name);
  869. X
  870. X    strcpy( short_name, name );
  871. X    i--;
  872. X    while ((i>0)&&(isdigit(short_name[i])))
  873. X    {    short_name[i] = '\0';
  874. X        i--;
  875. X    }
  876. X    return(short_name);
  877. X}
  878. X
  879. Xvoid next_name( act )
  880. X    ColorDef    *act;
  881. X/* collects color-names for the hash-table */
  882. X{
  883. X    if (act->pixel==Undefined)
  884. X    {    fprintf(stderr, "%s not defined.\n", act->name);
  885. X        return;
  886. X    }
  887. X    cname[color_names].name   = act->name;
  888. X    cname[color_names].length = strlen(act->name);
  889. X    cname[color_names].def    = act;
  890. X    color_names++;
  891. X}
  892. X
  893. XColorDef *make_entry( new )
  894. X    ColorDef *new;
  895. X/* allocates space for the data of a new color */
  896. X{
  897. XColorDef    *erg;
  898. X
  899. X    erg = (ColorDef *)malloc((unsigned) sizeof(ColorDef) );
  900. X    memcpy( (char *)erg, (char *)new, sizeof(ColorDef) );
  901. X    erg -> associated = NULL;
  902. X    erg -> brother    = NULL;
  903. X    erg -> pixel      = NotAllocated;
  904. X
  905. X    return( erg );
  906. X}
  907. X
  908. Xvoid new_color( new )
  909. X    ColorDef    *new;
  910. X/* searches for overlaps in the color-field and stores the new color */
  911. X{
  912. Xchar        *search_name;
  913. XColorDef    *act;
  914. XColorDef    *help;
  915. Xint        i;
  916. Xint        subname = 0;
  917. X
  918. X    search_name = cut_digits( new->name );
  919. X    subname = (search_name!=new->name);
  920. X
  921. X    act = find_color( search_name );
  922. X
  923. X    if (act)
  924. X    {    if (subname)        /* found and associated entry */
  925. X        {    help = act->associated;
  926. X            act->associated = make_entry( new );
  927. X            act->associated->associated = help;
  928. X        }
  929. X        else            /* strange: color declared twice ? */
  930. X        {    if (act->pixel==Undefined)
  931. X            {    memcpy( (char *)act, (char *)new, sizeof(ColorDef)-2*sizeof(ColorDef *) );
  932. X                act->pixel = NotAllocated;
  933. X            }
  934. X            else
  935. X            {
  936. X                help = act->brother;
  937. X                act->brother = make_entry( new );
  938. X                act->brother->brother = help;
  939. X            }
  940. X        }
  941. X    }
  942. X    else
  943. X    {    for (i=0;i<color_number;i++)
  944. X        {    if ( (new->r==color[i]->r) && (new->g==color[i]->g) && (new->b==color[i]->b) )    break;
  945. X        }
  946. X        if (i<color_number)
  947. X        {    help = color[i]->brother;
  948. X            color[i]->brother = make_entry( new );
  949. X            color[i]->brother->brother = help;
  950. X        }
  951. X        else
  952. X        {    if (subname)    /* indexed name found before original */
  953. X            {    act = (ColorDef *)malloc((unsigned) sizeof(ColorDef) );
  954. X                memset( (char *)act, (char)-1, sizeof(ColorDef) );
  955. X                act->pixel = Undefined;
  956. X                act->name  = (char *)malloc((unsigned) strlen(search_name)+1 );
  957. X                strcpy( act->name, search_name );
  958. X                act->associated = make_entry( new );
  959. X                act->brother = NULL;
  960. X                color[color_number++] = act;
  961. X            }
  962. X            else        /* found new color */
  963. X            {    color[color_number++] = make_entry( new );
  964. X            }
  965. X        }
  966. X    }
  967. X}
  968. X
  969. Xload_standard( act )
  970. X    ColorDef    *act;
  971. X{
  972. XXColor        exact_def,screen_def;
  973. X
  974. X    if (XLookupColor( display, DefaultColormapOfScreen(screen), act->name,
  975. X        &exact_def, &screen_def ))
  976. X    {    act->r = exact_def.red   >> 8;
  977. X        act->g = exact_def.green >> 8;
  978. X        act->b = exact_def.blue  >> 8;
  979. X    }
  980. X    new_color( act );
  981. X}
  982. X        
  983. X/*----------------------------------------------------------------------------*/
  984. X
  985. Xupdate_map()
  986. X/* sets unused pixels in my_map to the colors (with different intensity)
  987. X * of the DefaultColormap.
  988. X */
  989. X{
  990. XXColor    qcols[MAX_CELLS];
  991. Xint    i, j;
  992. X
  993. X    j=0;
  994. X    for (i=0;i<cells;i++)
  995. X    {    if (my_pixel[i]==0)    qcols[j++].pixel=i;
  996. X    }
  997. X    XQueryColors( display, DefaultColormapOfScreen(screen), qcols, j );
  998. X    for (i=0;i<j;i++)
  999. X    {    qcols[i].red   = ((long)qcols[i].red  *darkness)/100;
  1000. X        qcols[i].green = ((long)qcols[i].green*darkness)/100;
  1001. X        qcols[i].blue  = ((long)qcols[i].blue *darkness)/100;
  1002. X        qcols[i].flags = DoRed | DoGreen | DoBlue;
  1003. X    }
  1004. X    XStoreColors( display, my_map, qcols, j );
  1005. X}
  1006. X
  1007. Xcreate_new_map()
  1008. X/* get an own colormap */
  1009. X{
  1010. Xint        i;
  1011. XXColor        qcols[MAX_CELLS];
  1012. Xunsigned long    pixel[MAX_CELLS];
  1013. X
  1014. X/* allocate new colormap and copy the darkened colors of the default-map */
  1015. X    my_map = XCreateColormap( display, mw, 
  1016. X            XDefaultVisualOfScreen(screen), AllocAll);
  1017. X    if (my_map==(Colormap)0)
  1018. X    {    fprintf(stderr, "can't create colormap.\n" );
  1019. X        exit(0);
  1020. X    }
  1021. X    memset( (char *)my_pixel, (char)0, sizeof(my_pixel) );
  1022. X
  1023. X/* copy the default-map */
  1024. X    for (i=0;i<cells;i++)    qcols[i].pixel = i;
  1025. X    XQueryColors( display, DefaultColormapOfScreen(screen), qcols, cells );
  1026. X    for (i=0;i<cells;i++)
  1027. X    {    qcols[i].red   = ((long)qcols[i].red  *darkness)/100;
  1028. X        qcols[i].green = ((long)qcols[i].green*darkness)/100;
  1029. X        qcols[i].blue  = ((long)qcols[i].blue *darkness)/100;
  1030. X        qcols[i].flags = DoRed | DoGreen | DoBlue;
  1031. X    }
  1032. X    XStoreColors( display, my_map, qcols, cells );
  1033. X
  1034. X/* try to allocate the color_cells in the default-map */
  1035. X    if (XAllocColorCells( display, DefaultColormapOfScreen(screen), True, 
  1036. X        NULL, 0, pixel, color_number ))
  1037. X    {    int    high_value=0;
  1038. X
  1039. X    /* store the colors into my map and into and into the default-colormap
  1040. X     * as there are enough cells for both.
  1041. X     */
  1042. X        for (i=0;i<color_number;i++)
  1043. X        {    qcols[i].pixel = pixel[i];
  1044. X            qcols[i].flags = DoRed | DoGreen | DoBlue;
  1045. X            qcols[i].red   = color[i]->r << 8;
  1046. X            qcols[i].green = color[i]->g << 8;
  1047. X            qcols[i].blue  = color[i]->b << 8;
  1048. X            color[i]->pixel = pixel[i];
  1049. X            if (pixel[i]>=cells)
  1050. X            {    high_value=1;
  1051. X                break;
  1052. X            }
  1053. X            my_pixel[pixel[i]]=1;
  1054. X        }
  1055. X
  1056. X        if (high_value)
  1057. X        {    XFreeColors( display, DefaultColormapOfScreen(screen), 
  1058. X                pixel, color_number, 0 );
  1059. X            only_mine = 1;
  1060. X        }
  1061. X        else
  1062. X        {
  1063. X            XStoreColors( display, DefaultColormapOfScreen(screen), qcols, color_number );
  1064. X            XStoreColors( display, my_map, qcols, color_number );
  1065. X            only_mine = 0;
  1066. X        }
  1067. X    }
  1068. X    else    only_mine = 1;
  1069. X
  1070. X    if (only_mine)
  1071. X    {
  1072. X    /* pixels are just used from high to low numbers */
  1073. X        for (i=0;i<color_number;i++)
  1074. X        {
  1075. X            qcols[i].pixel = cells-i-1;
  1076. X            qcols[i].flags = DoRed | DoGreen | DoBlue;
  1077. X            qcols[i].red   = color[i]->r << 8;
  1078. X            qcols[i].green = color[i]->g << 8;
  1079. X            qcols[i].blue  = color[i]->b << 8;
  1080. X            color[i]->pixel = cells-i-1;
  1081. X            my_pixel[cells-i-1]=1;
  1082. X        }
  1083. X        XStoreColors( display, my_map, qcols, color_number );
  1084. X
  1085. X    /* afterwards, all free pixels of the default-map are allocated
  1086. X     * and set to the values of the new colormap.
  1087. X     */
  1088. X        i=0;
  1089. X        while( XAllocColorCells( display, DefaultColormapOfScreen(screen), True, 
  1090. X            NULL, 0, &pixel[i], 1 ) )
  1091. X        {    qcols[i].pixel = pixel[i];
  1092. X            i++;
  1093. X        }
  1094. X        XQueryColors( display, my_map, qcols, i );
  1095. X        XStoreColors( display, DefaultColormapOfScreen(screen), qcols, i );
  1096. X        XFreeColors( display, DefaultColormapOfScreen(screen), pixel, i, 0 );
  1097. X        only_mine = 1;
  1098. X    }
  1099. X
  1100. X/* the pixels for black, white have to be used from my_map, since
  1101. X * the entries of the DefaultColormap are possibly darkened.
  1102. X */
  1103. X    black = find_color( BLACK_STRING )->pixel;
  1104. X    my_pixel[black]++;
  1105. X    white = find_color( WHITE_STRING )->pixel;
  1106. X    my_pixel[white]++;
  1107. X    grey  = find_color( GREY_STRING )->pixel;
  1108. X    my_pixel[grey]++;
  1109. X}
  1110. X
  1111. Xdestroy_colormap()
  1112. X/* not used */
  1113. X{
  1114. Xunsigned long    pixel[MAX_CELLS];
  1115. Xint    i, j;
  1116. XColorDef *assoc, *erg;
  1117. X
  1118. X    XFreeColormap( display, my_map );
  1119. X    j=0;
  1120. X    if (!only_mine)
  1121. X    {    for (i=0;i<cells;i++)
  1122. X        {    if (my_pixel[i])    pixel[j++] = i;
  1123. X        }
  1124. X        XFreeColors( display, DefaultColormapOfScreen(screen), pixel, j, 0 );
  1125. X    }
  1126. X    my_map = NULL;
  1127. X    memset( (char *)my_pixel, (char)0, sizeof(my_pixel) );
  1128. X
  1129. X    for (i=0;i<color_number;i++)
  1130. X    {    erg = color[i];
  1131. X        do
  1132. X        {    erg->pixel = NotAllocated;
  1133. X            assoc = erg->associated;
  1134. X            while( assoc )
  1135. X            {    assoc->pixel = NotAllocated;
  1136. X                assoc = assoc->associated;
  1137. X            }
  1138. X            erg = erg->brother;
  1139. X        }
  1140. X        while (erg);
  1141. X    }
  1142. X}
  1143. X
  1144. X
  1145. END_OF_xcol.part1
  1146. if test 24317 -ne `wc -c <xcol.part1`; then
  1147.     echo shar: \"xcol.part1\" unpacked with wrong size!
  1148. fi
  1149. # end of overwriting check
  1150. fi
  1151. echo shar: End of shell archive.
  1152. # additional concatenation of splitted file
  1153. if test -f xcol.part2 ; then 
  1154.   echo '      concatenation of "xcol.part1" and "xcol.part2" to "xcol.c".'
  1155.   cat xcol.part1 xcol.part2 > xcol.c
  1156.   echo '      removing "xcol.part1" and "xcol.part2".'
  1157.   rm xcol.part1 xcol.part2
  1158. else
  1159.   echo '      unpack the second part now.'
  1160. fi
  1161. exit 0
  1162.  
  1163. dan
  1164. -----------------------------------------------------------
  1165.             O'Reilly && Associates
  1166.         argv@sun.com / argv@ora.com
  1167.        632 Petaluma Ave, Sebastopol, CA 95472 
  1168.      800-338-NUTS, in CA: 800-533-NUTS, FAX 707-829-0104
  1169.     Opinions expressed reflect those of the author only.
  1170.